package com.randi.common.utils.excel;

import com.randi.common.annotation.Excel;
import com.randi.common.core.domain.vo.FieldVO;
import org.apache.commons.lang3.ArrayUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 字段注解工具类
 *
 * @author randi
 */
public class ExcelFieldsUtil {

    private static List<Field> getTempFields(Class<?> clazz) {
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        return tempFields;
    }

    /**
     * 获取字段注解信息
     *
     * @param clazz clazz
     * @return 字段注解信息
     */
    public static List<Object[]> getFields(Class<?> clazz) {
        return getTempFields(clazz).stream()
                .filter(field -> field.isAnnotationPresent(Excel.class))
                .map(field -> {
                    field.setAccessible(true);
                    return new Object[]{field, field.getAnnotation(Excel.class)};
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取字段注解信息
     *
     * @param clazz         clazz
     * @param excludeFields 排除字段
     * @return 字段注解信息
     */
    public static List<Object[]> getFields(Class<?> clazz, String[] excludeFields) {
        if (ArrayUtils.isEmpty(excludeFields)) {
            return getFields(clazz);
        }
        return getTempFields(clazz).stream()
                .filter(field -> field.isAnnotationPresent(Excel.class) && !ArrayUtils.contains(excludeFields, field.getName()))
                .map(field -> {
                    field.setAccessible(true);
                    return new Object[]{field, field.getAnnotation(Excel.class)};
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取字段注解信息
     *
     * @param clazz         clazz
     * @param includeFields 包含字段
     * @param excludeFields 排除字段
     * @return 字段注解信息
     */
    public static List<Object[]> getFields(Class<?> clazz, String[] includeFields, String[] excludeFields) {
        if (ArrayUtils.isEmpty(includeFields)) {
            return getFields(clazz, excludeFields);
        }

        return getTempFields(clazz).stream()
                .filter(field -> field.isAnnotationPresent(Excel.class) &&
                        ArrayUtils.contains(includeFields, field.getName()) &&
                        !ArrayUtils.contains(excludeFields, field.getName()))
                .map(field -> {
                    field.setAccessible(true);
                    return new Object[]{field, field.getAnnotation(Excel.class)};
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取字段注解信息
     *
     * @param clazz clazz
     * @return 字段注解信息
     */
    public static List<FieldVO> getFieldVoList(Class<?> clazz) {
        return getFieldVoList(clazz, null);
    }

    /**
     * 获取字段注解信息
     *
     * @param clazz         clazz
     * @param excludeFields 排除字段
     * @return FieldVoList
     */
    public static List<FieldVO> getFieldVoList(Class<?> clazz, String[] excludeFields) {
        return Arrays.stream(clazz.getDeclaredFields())
                .filter(field -> field.isAnnotationPresent(Excel.class) && !ArrayUtils.contains(excludeFields, field.getName()))
                .map(field -> {
                    field.setAccessible(true);
                    Excel attr = field.getAnnotation(Excel.class);
                    return new FieldVO(attr.name(), field.getName());
                })
                .collect(Collectors.toList());

    }

}
